#ifndef NETWORKNODE_H
#define NETWORKNODE_H

#include "enet/enet.h"

#include "types.h"

#include <string>

namespace sde {
    
    class NetworkNode {
    protected:
        ENetHost* host;
        ENetPeer* peer;
        ENetEvent event;
        
        bool server;
        
        ENetPacket* createPacket();
        
        virtual void receive(ENetPeer* sender, ENetPacket* packet) {}
        void send(ENetPeer* target, ENetPacket* packet);
        
        virtual void onConnected(ENetPeer* peer) {}
        virtual void onDisconnected(ENetPeer* peer) {}
        
        void writeBool(ENetPacket* packet, bool b);
        void writeChar(ENetPacket* packet, unsigned char c);
        void writeInt(ENetPacket* packet, int i);
        void writeFloat(ENetPacket* packet, float f);
        void writeString(ENetPacket* packet, std::string s);
        void writeVar(ENetPacket* packet, Var v);
        void writeVarMap(ENetPacket* packet, VarMap vars);
        
        bool readBool(ENetPacket* packet, int& pos);
        unsigned char readChar(ENetPacket* packet, int& pos);
        int readInt(ENetPacket* packet, int& pos);
        float readFloat(ENetPacket* packet, int& pos);
        std::string readString(ENetPacket* packet, int& pos);
        Var readVar(ENetPacket* packet, int& pos);
        VarMap readVarMap(ENetPacket* packet, int& pos);
        
    public:
        NetworkNode(bool _server);
        
        virtual void connect(std::string hostName, int port);
        virtual void disconnect();
        
        void pump(int time);
    
        enum NetworkData {
        boolData = 0,
        intData,
        floatData,
        stringData,
        vector2Data,
        vector3Data,
        quaternionData,
        nullData
        };
        
        enum NetworkCmd {
        pingCmd = 0,
        pongCmd,
        modulesCmd,
        initStateCmd,
        makeObjectNameCmd,
        makeObjectCmd,
        objectNameCmd,
        setVarCmd,
        distSetVarCmd,
        requestVarCmd,
        destroyObjectCmd,
        runActionCmd,
        actionNameCmd,
        subscribeRpcCmd,
        rpcCmd,
        rpcResultCmd,
        registerSetVarCmd,
        };
    };
}

#endif
